﻿@using System.Timers

@inject IContactFilters Filters
@implements IDisposable
Filter by:
<input type="text" autofocus @bind-value="FilterText" @bind-value:event="oninput" />
<button class="btn btn-danger" @onclick="@(() => FilterText = string.Empty)">Clear</button>
Filter on: <select @bind="SelectedColumn">
    @foreach (ContactFilterColumns column in (ContactFilterColumns[])Enum.GetValues(typeof(ContactFilterColumns)))
    {
        <option @attributes="Selected(column)" value="@((int)column)">@(column.ToString())</option>
    }
</select>

@code {
    /// <summary>
    /// Get a reference to the global <see cref="GridWrapper"/>.
    /// </summary>
    [CascadingParameter]
    public GridWrapper Wrapper { get; set; }

    /// <summary>
    /// Wait period in (ms) after the user stops typing.
    /// </summary>
    const int DebounceMs = 300;

    /// <summary>
    /// Timer for debounce.
    /// </summary>
    Timer timer;

    /// <summary>
    /// When ready.
    /// </summary>
    protected override void OnInitialized()
    {
        // grab filter
        filterText = Filters.FilterText;

        // grab column to filter on
        selectedColumn = (int)(Filters.FilterColumn);

        base.OnInitialized();
    }

    /// <summary>
    /// Sets selected attribute.
    /// </summary>
    /// <param name="column">The <see cref="ContactFilterColumns"/> being evaluated.</param>
    /// <returns>The proper attribute to select the option.</returns>
    private IEnumerable<KeyValuePair<string, object>> Selected(ContactFilterColumns column)
    {
        if ((int)column == selectedColumn)
        {
            return new[] { new KeyValuePair<string, object>("selected", (object)"selected") };
        }
        return Enumerable.Empty<KeyValuePair<string, object>>();
    }

    private int selectedColumn;

    /// <summary>
    /// Column to filter on.
    /// </summary>
    private int SelectedColumn
    {
        get => selectedColumn;
        set
        {
            if (value != selectedColumn)
            {
                selectedColumn = value;
                Filters.FilterColumn = (ContactFilterColumns)selectedColumn;
                FilterText = string.Empty;
            }
        }
    }

    private string filterText;

    /// <summary>
    /// Text to filter on.
    /// </summary>
    private string FilterText
    {
        get => filterText;
        set
        {
            if (value != filterText)
            {
                filterText = value;
                // more text means restart the debounce timer
                if (timer != null)
                {
                    timer.Dispose();
                }
                timer = new Timer(DebounceMs);
                timer.Elapsed += NotifyTimerElapsed;
                timer.Enabled = true;
            }
        }
    }

    /// <summary>
    /// Fired after debounce time.
    /// </summary>
    /// <param name="sender">Timer.</param>
    /// <param name="e">Event args.</param>
    private async void NotifyTimerElapsed(object sender, ElapsedEventArgs e)
    {
        timer.Dispose();
        timer = null;
        if (Filters.FilterText != filterText)
        {
            // notify the controls
            Filters.FilterText = filterText.Trim();
            await InvokeAsync(() => Wrapper.FilterChanged.InvokeAsync(this));
        }
    }

    /// <summary>
    /// Disposable pattern - override to dispose any ticking timers.
    /// </summary>
    /// <param name="disposing"><c>True</c> when disposing.</param>
    public void Dispose()
    {
        if (timer != null)
        {
            timer.Dispose();
            timer = null;
        }
    }
}
